home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 9825 / 9825.xpi / chrome / content / smarterwiki.js < prev   
Text File  |  2010-01-13  |  46KB  |  1,096 lines

  1. //to add: clipboard manager?
  2. /*
  3. Note: while this addon uses the jQuery library, which contains eval()s,
  4. it does not cause any of them to be invoked. I believe that jQuery uses
  5. those eval()s for processing json, but this addon no longer uses json.
  6.  
  7. Also, jQuery.noConflict() is invoked, which prevents namespace conflicts.
  8. */
  9.  
  10. var SmarterWiki = function()
  11. {
  12.     var DEBUG = true;
  13.     var LOAD_CSS_LOCALLY = true;
  14.     var LOAD_JS_LOCALLY = true;
  15.     
  16.     
  17.     var consoleService = Components.classes["@mozilla.org/consoleservice;1"]
  18.                                .getService(Components.interfaces.nsIConsoleService);
  19.     var prefManager = Components.classes["@mozilla.org/preferences-service;1"]
  20.                                .getService(Components.interfaces.nsIPrefBranch);
  21.     var faviconService = Components.classes["@mozilla.org/browser/favicon-service;1"]
  22.                                .getService(Components.interfaces.nsIFaviconService);
  23.     var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  24.                                .getService(Components.interfaces.nsIIOService);  
  25.     var bookmarksService = Components.classes["@mozilla.org/browser/nav-bookmarks-service;1"]
  26.                                .getService(Components.interfaces.nsINavBookmarksService);
  27.     var historyService = Components.classes["@mozilla.org/browser/nav-history-service;1"]
  28.                                .getService(Components.interfaces.nsINavHistoryService);
  29.     var taggingService = Components.classes["@mozilla.org/browser/tagging-service;1"]
  30.                                .getService(Components.interfaces.nsITaggingService);
  31.     var downloadManager = Components.classes["@mozilla.org/download-manager;1"]
  32.                                .getService(Components.interfaces.nsIDownloadManager);
  33.     var downloadManagerUI = Components.classes["@mozilla.org/download-manager-ui;1"]
  34.                                .getService(Components.interfaces.nsIDownloadManagerUI);
  35.     var styleSheetService = Components.classes["@mozilla.org/content/style-sheet-service;1"]
  36.                                .getService(Components.interfaces.nsIStyleSheetService);
  37.  
  38.     var nativeJSON = Components.classes["@mozilla.org/dom/json;1"].createInstance(Components.interfaces.nsIJSON);
  39.     
  40.  
  41.  
  42.  
  43.     var prefPrefix = "extensions.smarterwiki.";
  44.     var onuninstallURL = function(install_time, install_duration)
  45.     {
  46.         return "http://smarterfox.com/smarterwiki/uninstalled/?install_time=" + install_time + "&install_duration=" + install_duration;
  47.     };
  48.     var ondisableURL = function(install_time, install_duration)
  49.     {
  50.         return "http://smarterfox.com/smarterwiki/disabled/?install_time=" + install_time + "&install_duration=" + install_duration;
  51.     };
  52.     var oninstallURL = function(lastVersion, currentVersion)
  53.     {
  54.         return "http://smarterfox.com/smarterwiki/installed/?from_ver=" + lastVersion + "&to_ver=" + currentVersion;
  55.     };
  56.     var onupdateURL = function(lastVersion, currentVersion)
  57.     {
  58.         return "http://smarterfox.com/smarterwiki/updated/?from_ver=" + lastVersion + "&to_ver=" + currentVersion;
  59.     };
  60.  
  61.     var qlauncher_js = null;
  62.     var qlauncher_css = null;
  63.     var popup_bubble_js = null;
  64.     var popup_bubble_css = null;
  65.     var related_articles_js = null;
  66.     var linkify_js = null;
  67.     var related_searches_js = null;
  68.     var related_searches_css = null;
  69.     var endless_pages_js = null;
  70.     var endless_pages_css = null;
  71.     var related_search_results_js = null;
  72.     var related_search_results_css = null;
  73.     var jquery_js = null;
  74.  
  75.  
  76.  
  77.  
  78.     var LOG = function(msg, prefix)
  79.     {
  80.         var enabled = DEBUG;
  81.         if(!prefix)
  82.         {
  83.             prefix = "smarterwiki: ";
  84.         }
  85.         if(enabled)
  86.         {
  87.             consoleService.logStringMessage(prefix + msg);
  88.         }
  89.     }
  90.  
  91.     var get_logger = function(prefix)
  92.     {
  93.         return function(msg)
  94.         {
  95.             LOG(msg, prefix);
  96.         };
  97.     }
  98.  
  99.     var searchWikipediaURL = function(terms)
  100.     {
  101.         /*
  102.         if exact match is found in Wikipedia, the user is sent to Wikipedia.
  103.         else the user is redirected to Google search.
  104.         */
  105.         return "http://smarterfox.com/wikisearch/search?q=" + encodeURIComponent(terms);
  106.         //return "http://www.google.com/search?q=" + terms + " site:wikipedia.org" //search more than a specific wikipedia such as en.wikipedia.org
  107.     };
  108.     
  109.     var asyncRequestText = function(url, handler)
  110.     {
  111.         var req = new XMLHttpRequest();
  112.         req.open("GET", url);
  113.         req.addEventListener("load", function(event)
  114.         {
  115.             handler(req.responseText);
  116.         }, false);
  117.         req.send(null);
  118.     };
  119.  
  120.  
  121.     var async_get_js_factory = function(get_var, set_var, filename)
  122.     {
  123.         return function(callback)
  124.         {
  125.             if(get_var() == null)
  126.             {
  127.                 var url = (LOAD_JS_LOCALLY ? "chrome://smarterwiki/content/" : "http://static.smarterfox.com/media/smarterwiki/") + 
  128.                             filename;
  129.                 asyncRequestText(url, function(text)
  130.                 {
  131.                     set_var(text);
  132.                     callback(text);
  133.                 });
  134.             }
  135.             else
  136.             {
  137.                 callback(get_var());
  138.             }
  139.         };
  140.     };
  141.     var async_get_qlauncher_js = async_get_js_factory(
  142.         function(){return qlauncher_js;},
  143.         function(text){qlauncher_js = text;},
  144.         "qlauncher.js"
  145.     );        
  146.     var async_get_popup_bubble_js = async_get_js_factory(
  147.         function(){return popup_bubble_js;},
  148.         function(text){popup_bubble_js = text;},
  149.         "popup_bubble.js"
  150.     );        
  151.     var async_get_related_articles_js = async_get_js_factory(
  152.         function(){return related_articles_js;},
  153.         function(text){related_articles_js = text;},
  154.         "related_articles.js"
  155.     );        
  156.     var async_get_linkify_js = async_get_js_factory(
  157.         function(){return linkify_js;},
  158.         function(text){linkify_js = text;},
  159.         "linkify.js"
  160.     );        
  161.     var async_get_related_searches_js = async_get_js_factory(
  162.         function(){return related_searches_js;},
  163.         function(text){related_searches_js = text;},
  164.         "related_searches.js"
  165.     );    
  166.     var async_get_endless_pages_js = async_get_js_factory(
  167.         function(){return endless_pages_js;},
  168.         function(text){endless_pages_js = text;},
  169.         "endless_pages.js"
  170.     );
  171.     var async_get_related_search_results_js = async_get_js_factory(
  172.         function(){return related_search_results_js;},
  173.         function(text){related_search_results_js = text;},
  174.         "related_search_results.js"
  175.     );
  176.     
  177.     
  178.     var loadStuff = function()
  179.     {
  180.         async_get_qlauncher_js(function(){});
  181.         async_get_popup_bubble_js(function(){});
  182.         async_get_related_articles_js(function(){});
  183.         async_get_linkify_js(function(){});
  184.         async_get_related_searches_js(function(){});
  185.         async_get_endless_pages_js(function(){});
  186.         async_get_related_search_results_js(function(){});
  187.  
  188.         async_load_qlauncher_css();
  189.         async_load_popup_bubble_css();
  190.         async_load_related_searches_css();
  191.         async_load_endless_pages_css();
  192.         async_load_related_search_results_css();
  193.  
  194.         asyncRequestText("chrome://smarterwiki/content/jquery-1.3.2.min.js", function(text)
  195.         {
  196.             jquery_js = text;
  197.         });
  198.  
  199.         asyncRequestText("chrome://smarterwiki/content/jquery-1.2.6.js", function(text)
  200.         {
  201.             var jquery_js_old = text;
  202.             eval(jquery_js_old);//load here to prevent namespace collisions
  203.             SmarterWiki.$ = jQuery.noConflict(true);
  204.         });
  205.     };
  206.     
  207.     var loadCSSText = function(css_text)
  208.     {
  209.         var uri = ioService.newURI("data:text/css;base64," + btoa(css_text), null, null);
  210.         if(!styleSheetService.sheetRegistered(uri, styleSheetService.USER_SHEET))
  211.         {
  212.             styleSheetService.loadAndRegisterSheet(uri, styleSheetService.USER_SHEET);
  213.         }
  214.     };
  215.     var async_load_css_factory = function(get_var, set_var, filename)
  216.     {
  217.         return function()
  218.         {
  219.             if(get_var() == null)
  220.             {
  221.                 var url = (LOAD_CSS_LOCALLY ? "chrome://smarterwiki/skin/" : "http://static.smarterfox.com/media/smarterwiki/") + 
  222.                             filename;
  223.                 asyncRequestText(url, function(text)
  224.                 {
  225.                     set_var(text);
  226.                     loadCSSText(text);
  227.                 });
  228.             }
  229.             //else aready loaded, no need to do it again
  230.         };            
  231.     };
  232.     var async_load_qlauncher_css = async_load_css_factory(
  233.             function(){return qlauncher_css;}, 
  234.             function(text){qlauncher_css = text;},
  235.             "qlauncher.css");
  236.     var async_load_popup_bubble_css = async_load_css_factory(
  237.             function(){return popup_bubble_css;}, 
  238.             function(text){popup_bubble_css = text;},
  239.             "popup_bubble.css");
  240.     var async_load_related_searches_css = async_load_css_factory(
  241.             function(){return related_searches_css;}, 
  242.             function(text){related_searches_css = text;},
  243.             "related_searches.css");
  244.     var async_load_endless_pages_css = async_load_css_factory(
  245.             function(){return endless_pages_css;}, 
  246.             function(text){endless_pages_css = text;},
  247.             "endless_pages.css");
  248.     var async_load_related_search_results_css = async_load_css_factory(
  249.             function(){return related_search_results_css;}, 
  250.             function(text){related_search_results_css = text;},
  251.             "related_search_results.css");
  252.  
  253.     
  254.     var setupAwesomebar = function()
  255.     {
  256.         if(prefManager.getBoolPref(prefPrefix + "enhance_urlbar"))
  257.         {
  258.             var urlbar = document.getElementById("urlbar");
  259.             urlbar.setAttribute("autocompletesearch", "smarterwiki-search");//"history smarterwiki-trunc-hist");//
  260.             urlbar.maxRows = 10;
  261.         }
  262.  
  263.         /*
  264.         //override handleURLBarCommand
  265.         var old_handleURLBarCommand = handleURLBarCommand;
  266.         handleURLBarCommand = function(aTriggeringEvent)
  267.         {
  268.             if(gURLBar.value == "http://google.com")
  269.             {
  270.                 gURLBar.value = "http://yahoo.com";
  271.             }
  272.             return old_handleURLBarCommand(aTriggeringEvent);
  273.         }
  274.         */
  275.     };
  276.     
  277.     var setupExitSurvey = function()
  278.     {
  279.         var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  280.         observerService.addObserver(
  281.             {
  282.                 observe: function(p_Subject, p_Topic, p_Data)
  283.                 {
  284.                     if(p_Topic == "em-action-requested")
  285.                     {
  286.                         p_Subject.QueryInterface(Components.interfaces.nsIUpdateItem);
  287.                         if(p_Subject.id == "smarterwiki@wikiatic.com")
  288.                         {
  289.                             var install_time = parseInt(prefManager.getCharPref(prefPrefix + "install-time"));//too big for int pref
  290.                             var install_duration = new Date().getTime() - install_time;
  291.                             if(p_Data == "item-uninstalled")
  292.                             {
  293.                                 gBrowser.selectedTab = gBrowser.addTab(onuninstallURL(install_time, install_duration));
  294.                             }
  295.                             else if(p_Data == "item-disabled")
  296.                             {
  297.                                 gBrowser.selectedTab = gBrowser.addTab(ondisableURL(install_time, install_duration));
  298.                             }
  299.                         }
  300.                     }
  301.                 }
  302.             }, 
  303.         "em-action-requested", false);
  304.     };
  305.     
  306.     var insertAffCode = function(url)
  307.     {
  308.         if(url.search("^http(|s)://([^/]*\\.)?amazon\\.com.*$") != -1 &&
  309.            url.search(/.*tag=.*/) == -1 && url.search(/.*obidos.*/) == -1) //don't overwrite aff codes & cannot handle obidos
  310.         {
  311.             var aff_code = "smtfx1-20";
  312.             if(url.search("\\?") != -1)
  313.             {
  314.                 return url + "&tag=" + aff_code;//has args. tack on end
  315.             }
  316.             else
  317.             {
  318.                 return url + "?tag=" + aff_code; //no args. add
  319.             }
  320.         }
  321.         return url;
  322.     };
  323.  
  324.     var openNewTab = function(url)
  325.     {
  326.         if(prefManager.getBoolPref(prefPrefix + "insert_aff_code"))
  327.         {
  328.             url = insertAffCode(url);
  329.         }
  330.         gBrowser.selectedTab = gBrowser.addTab(url);
  331.     };
  332.     
  333.     var should_show_yandex = function()
  334.     {
  335.         var yandex_lang_codes = ['ru', 'rus',
  336.             'uk', 'ukr',
  337.             'be', 'bel',
  338.             'kk', 'kaz',
  339.             'uz', 'uzb',
  340.             'kaa', 'kaa',
  341.             'tk', 'tuk',
  342.             'tut', 'gag',
  343.             'mo', 'mol',
  344.             'ky', 'kir',
  345.             'et', 'est',
  346.             'lt', 'lit',
  347.             'lv', 'lav',
  348.             'hy', 'arm', 'hye', 
  349.             'az', 'aze',
  350.             'ka', 'geo', 'kat',
  351.             'tg', 'tgk'];
  352.         
  353.         var show_yandex = false;
  354.         for(var x = 0; x < yandex_lang_codes.length; x++)
  355.         {
  356.             if(navigator.language == yandex_lang_codes[x] || navigator.language.indexOf(yandex_lang_codes[x] + "-") == 0)
  357.             {
  358.                 show_yandex = true;
  359.             }
  360.         }
  361.         return show_yandex;
  362.     };    
  363.     
  364.     var displayWelcomePage = function()
  365.     {
  366.         var currentVersion = Application.extensions.get("smarterwiki@wikiatic.com").version;
  367.         var lastVersion = prefManager.getCharPref(prefPrefix + "last-version");
  368.         var isFirstRun = (lastVersion == "firstrun");
  369.         if(lastVersion != currentVersion)
  370.         {
  371.             setTimeout(function() 
  372.             {
  373.                 if(isFirstRun)
  374.                 {
  375.                     if(should_show_yandex())
  376.                     {
  377.                         prefManager.setBoolPref(prefPrefix + "search_yandex", true);
  378.                         prefManager.setBoolPref(prefPrefix + "search_google", false);
  379.                     }                        
  380.                     openNewTab(oninstallURL(lastVersion, currentVersion));
  381.                 }
  382.                 else
  383.                 {
  384.                     if(should_show_yandex())
  385.                     {
  386.                         prefManager.setBoolPref(prefPrefix + "search_yandex", true);
  387.                         prefManager.setBoolPref(prefPrefix + "search_google", false);
  388.                     }                        
  389.                     openNewTab(onupdateURL(lastVersion, currentVersion));
  390.                 }               
  391.             }, 100);
  392.         }
  393.         prefManager.setCharPref(prefPrefix + "last-version", currentVersion);
  394.         if(isFirstRun)
  395.         {
  396.             prefManager.setCharPref(prefPrefix + "install-time", new Date().getTime());
  397.         }
  398.     };
  399.  
  400.     var getFaviconURL = function(pageURL)
  401.     {
  402.         if("about:blank" == pageURL)
  403.         {
  404.             return "about:blank";
  405.         }
  406.         var pageURI = ioService.newURI(pageURL, null, null);
  407.         var getFaviconForPage = function(uri)
  408.         {
  409.             try
  410.             {
  411.                 return faviconService.getFaviconForPage(uri).spec;
  412.             }
  413.             catch(error)
  414.             {
  415.                 return null;
  416.             }
  417.         };
  418.  
  419.         var hardcodedRedirects = {};
  420.         hardcodedRedirects["http://reader.google.com"] = "http://www.google.com/reader/view/";
  421.  
  422.         var favicon_url = getFaviconForPage(pageURI);
  423.         if(favicon_url == null)
  424.         {
  425.             var pageURI2 = pageURI.clone();
  426.             pageURI2.host = "www." + pageURI2.host;
  427.             favicon_url = getFaviconForPage(pageURI2);
  428.             if(favicon_url == null) 
  429.             {
  430.                 if(pageURL in hardcodedRedirects)
  431.                 {
  432.                     favicon_url = getFaviconForPage(ioService
  433.                         .newURI(hardcodedRedirects[pageURL], null, null));
  434.                 }
  435.                 if(favicon_url == null)
  436.                 {
  437.                     pageURI2 = pageURI.clone();
  438.                     pageURI2.path = "favicon.ico";
  439.                     favicon_url = pageURI2.spec;
  440.                 }
  441.             }
  442.         }
  443.  
  444.         return favicon_url;
  445.     };
  446.     
  447.     var queryBookmarks = function(bookmarkFolderId)
  448.     {
  449.         //
  450.         var options = historyService.getNewQueryOptions();
  451.         var query = historyService.getNewQuery();    
  452.         
  453.         query.setFolders([bookmarkFolderId], 1);
  454.         
  455.         var result = historyService.executeQuery(query, options);
  456.         var rootNode = result.root;
  457.         rootNode.containerOpen = true;
  458.  
  459.         var bookmarkNodes = [];
  460.         for(var i = 0; i < rootNode.childCount; i++) // iterate over the immediate children of this folder
  461.         {
  462.             var node = rootNode.getChild(i);
  463.             bookmarkNodes.push(node);
  464.         }
  465.  
  466.         rootNode.containerOpen = false; // IMPORTANT: close a container after using it!
  467.  
  468.         return bookmarkNodes;
  469.     };
  470.     
  471.     var getQlauncherFolderId = function(create)
  472.     {
  473.         // Application.bookmarks.toolbar.addFolder("qLauncher");
  474.         var qlauncherFolderId = bookmarksService.getChildFolder(bookmarksService.bookmarksMenuFolder, "qLauncher");
  475.         if(qlauncherFolderId == 0 && create)
  476.         {
  477.             qlauncherFolderId = bookmarksService.createFolder(bookmarksService.bookmarksMenuFolder, 
  478.                 "qLauncher", 0);
  479.         }
  480.         return qlauncherFolderId;
  481.     };
  482.     
  483.     var hasShortcuts = function()
  484.     {
  485.         var qlauncherFolderId = getQlauncherFolderId(false);
  486.         return qlauncherFolderId != 0;
  487.     };
  488.     
  489.     var addShortcut = function(title, uri)
  490.     {
  491.         var qlauncherFolderId = getQlauncherFolderId(true);
  492.         bookmarksService.insertBookmark(qlauncherFolderId, ioService.newURI(uri, null, null), -1, title);        
  493.         taggingService.tagURI(ioService.newURI(uri, null, null), ["qlauncher:"]);
  494.     };
  495.     
  496.     var migrateBookmarks = function()
  497.     {
  498.         var qlauncherToolbarFolderId = bookmarksService.getChildFolder(bookmarksService.toolbarFolder, "qLauncher");
  499.         if(qlauncherToolbarFolderId == 0)
  500.         {
  501.             return;
  502.         }
  503.         
  504.         var qlauncherMenuFolderId = getQlauncherFolderId(true);
  505.         
  506.         for each(var bookmarkNode in queryBookmarks(qlauncherToolbarFolderId))
  507.         {
  508.             bookmarksService.insertBookmark(qlauncherMenuFolderId, ioService.newURI(bookmarkNode.uri, null, null), -1, bookmarkNode.title);
  509.         }
  510.         
  511.         bookmarksService.removeItem(qlauncherToolbarFolderId);
  512.     };
  513.     
  514.     var initQlauncherBookmarks = function()
  515.     {
  516.         var qlauncherFolderId = getQlauncherFolderId(true);
  517.         if(queryBookmarks(qlauncherFolderId).length == 0)
  518.         {
  519.             //add the default bookmarks
  520.             var defaultBookmarks = [
  521.                     ["a", "Amazon", "http://www.amazon.com"],
  522.                     ["d", "Download Squad", "http://www.downloadsquad.com"],
  523.                     ["f", "Facebook", "http://www.facebook.com"],
  524.                     ["g", "Digg", "http://digg.com"],
  525.                     ["l", "Lifehacker", "http://lifehacker.com"],
  526.                     ["m", "Mashable", "http://mashable.com"],
  527.                     ["n", "NYTimes", "http://nytimes.com"],
  528.                     ["r", "ReadWriteWeb", "http://www.readwriteweb.com"],
  529.                     ["s", "MySpace", "http://www.myspace.com", ],
  530.                     ["u", "YouTube", "http://www.youtube.com"],
  531.                     ["w", "Wikipedia", "http://en.wikipedia.org/wiki/Main_Page"],
  532.                     //["x", "Reader", "http://www.google.com/reader/view/"],
  533.                 ];
  534.             for each(var bkmk in defaultBookmarks)
  535.             {
  536.                 var tag = "qlauncher:" + bkmk[0];
  537.                 var title = bkmk[1];
  538.                 var uri = bkmk[2];
  539.                 bookmarksService.insertBookmark(qlauncherFolderId, ioService.newURI(uri, null, null), -1, title);
  540.                 taggingService.tagURI(ioService.newURI(uri, null, null), [tag]);
  541.             }
  542.         }
  543.  
  544.         return qlauncherFolderId;
  545.     };
  546.     
  547.     var removeBookmark = function(itemId)
  548.     {
  549.         bookmarksService.removeItem(itemId);
  550.     };
  551.     
  552.     var getShortcuts = function()
  553.     {
  554.         var qlauncherFolderId = initQlauncherBookmarks();
  555.         var shortcuts = [];
  556.         for each(var bookmarkNode in queryBookmarks(qlauncherFolderId))
  557.         {
  558.             var uri = bookmarkNode.uri;
  559.             var tags = taggingService.getTagsForURI(ioService.newURI(uri, null, null), {});
  560.             var shortcut_key = null;
  561.             for each(var tag in tags)
  562.             {
  563.                 var m = /qlauncher:(.?)/.exec(tag);
  564.                 if(m != null)
  565.                 {
  566.                     shortcut_key = m[1].toLowerCase();
  567.                     break;
  568.                 }
  569.             }
  570.             shortcuts.push([shortcut_key, getFaviconURL(uri), bookmarkNode.title, uri, bookmarkNode.itemId]);
  571.         }
  572.         return shortcuts;
  573.     };
  574.  
  575.     var doAutoCopy = function()
  576.     {
  577.         if(prefManager.getBoolPref(prefPrefix + "auto_copy_selected"))
  578.         {
  579.             var selection = document.commandDispatcher.focusedWindow.getSelection();
  580.             if(selection.toString())
  581.             {
  582.                 goDoCommand('cmd_copy');//clipboardHelper.copyString(selection.toString());  
  583.             }
  584.             // goDoCommand('cmd_copy'); //doing this will allow copy of text fields but make life more difficult
  585.         }
  586.     };
  587.     
  588.     var showBookmarkCurrentPageEdit = function()
  589.     {
  590.         PlacesCommandHook.bookmarkCurrentPage(true);
  591.     };
  592.     
  593.  
  594.     var filename_from_url = function(url)
  595.     {
  596.         var patt = /.*\/([^\/]+?)(?:\/$|$)/;
  597.         var match = patt.exec(url);
  598.         
  599.         var filename = match[1] ? match[1].replace(/[\\\/:*?"<>|]/g, "_") : "_";
  600.         return filename.substring(0, 25);
  601.     };
  602.     
  603.     var downloadURLs = function(download_infos)
  604.     {
  605.         const xulURL = "chrome://smarterwiki/content/folder_chooser.xul";
  606.         const features = "chrome, all, dialog=no, centerscreen";
  607.         var callback = function(folder)//folder is nsILocalFile
  608.         {
  609.             LOG("downloading " + download_infos.length + " urls");
  610.             var callback2 = function()
  611.             {
  612.                 var download = null;
  613.                 for(var i = 0; i < download_infos.length; i++)
  614.                 {
  615.                     var source_uri = download_infos[i][0];
  616.                     var referrerURI = download_infos[i][1];
  617.                     var file_ext = download_infos[i][2] ? download_infos[i][2] : "";
  618.                     var filename = download_infos[i][3];
  619.                     var target_file = folder.clone();
  620.                     
  621.                     
  622.                     var base_name = filename;
  623.                     if(!base_name)
  624.                     {
  625.                         base_name = filename_from_url(source_uri.spec);
  626.                         if(file_ext)
  627.                         {
  628.                             var m = /\.([^.]*)$/.exec(base_name);
  629.                             if(!m || m.length != 2 || m[1] != file_ext)
  630.                             {
  631.                                 base_name = base_name + "." + file_ext;
  632.                             }
  633.                         }
  634.                     }
  635.                     
  636.                     target_file.append(base_name);
  637.                     for(var z = 1; true; z++)
  638.                     {
  639.                         if(target_file.exists())
  640.                         {
  641.                             target_file.leafName = "(" + z + ") " + base_name;
  642.                         }
  643.                         else
  644.                         {
  645.                             try
  646.                             {
  647.                                 target_file.create(0, 0644);//this marks the file as being created so that we do not overwrite it later
  648.                             }
  649.                             catch(e)
  650.                             {
  651.                                 LOG("Cannot create: " + target_file.leafName);
  652.                             }
  653.                             break;
  654.                         }
  655.                     }
  656.                     var target_uri = ioService.newFileURI(target_file)
  657.                     var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
  658.                                         .createInstance(Components.interfaces.nsIWebBrowserPersist);
  659.                     persist.persistFlags = Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
  660.                     download = downloadManager.addDownload(Components.interfaces.nsIDownloadManager.DOWNLOAD_TYPE_DOWNLOAD, 
  661.                                                            source_uri, target_uri, target_file.leafName, null, 
  662.                                                            Date.now() * 1000, null, persist);
  663.                     persist.progressListener = download.QueryInterface(Components.interfaces.nsIWebProgressListener);
  664.                     persist.saveURI(source_uri, null, referrerURI, null, null, target_file);
  665.                     //set_message("Downloading %1 urls - this may take a while, please wait...".replace(/%1/g, download_infos.length - i - 1));
  666.                 }
  667.                 if(download)
  668.                 {
  669.                     if(downloadManagerUI.visible)
  670.                     {
  671.                         if(prefManager.getBoolPref("browser.download.manager.focusWhenStarting"))
  672.                         {
  673.                             downloadManagerUI.getAttention();
  674.                         }
  675.                     }
  676.                     else
  677.                     {
  678.                         if(prefManager.getBoolPref("browser.download.manager.showWhenStarting"))
  679.                         {
  680.                             downloadManagerUI.show(null, download, Components.interfaces.nsIDownloadManagerUI.REASON_NEW_DOWNLOAD);
  681.                         }
  682.                     }
  683.                 }
  684.                 //message_window.close();
  685.             };
  686.             var message_window = window.openDialog("chrome://smarterwiki/content/message_window.xul", "", features, 
  687.                                     SmarterWiki.strbundle.getString("please_wait"), 
  688.                                     SmarterWiki.strbundle.getString("downloading_please_wait").replace(/%1/g, download_infos.length),
  689.                                     callback2);
  690.         };
  691.         window.openDialog(xulURL, "", features, callback);
  692.     };
  693.  
  694.     return {
  695.         init: function()
  696.         {
  697.             loadStuff();
  698.  
  699.             setupAwesomebar();
  700.             
  701.             setupExitSurvey();
  702.             
  703.             displayWelcomePage();
  704.                         
  705.             SmarterWiki.strbundle = document.getElementById("smarterwiki_strings");
  706.             
  707.             migrateBookmarks();
  708.             
  709.             var menu = document.getElementById("contentAreaContextMenu");
  710.             menu.addEventListener("popupshowing", SmarterWiki.onPopupshowing, false);
  711.  
  712.             var appcontent = document.getElementById("appcontent");   // browser
  713.             if(appcontent)
  714.             {
  715.                 appcontent.addEventListener("DOMContentLoaded", SmarterWiki.onPageLoad, true);
  716.                 /*
  717.                 //injecting jQuery on DOMContentLoaded can cause problems. :(
  718.                 appcontent.addEventListener("load", SmarterWiki.onPageLoad, true);
  719.                 */
  720.             }
  721.         },
  722.         
  723.         onmouseup: function(event)
  724.         {
  725.             doAutoCopy();
  726.         },    
  727.         
  728.         onkeydown: function(event)
  729.         {
  730.             doAutoCopy();
  731.         },
  732.         
  733.         onmousedown: function(event)
  734.         {
  735.             if(
  736.                 (prefManager.getBoolPref(prefPrefix + "enable_middle_click_paste") && event.button == 1) ||                
  737.                 (prefManager.getBoolPref(prefPrefix + "enable_right_click_paste") && event.button == 2)
  738.             )
  739.             {
  740.                 setTimeout(function() // allow focus to shift
  741.                 {
  742.                     goDoCommand('cmd_paste');
  743.                 }, 10);
  744.             }
  745.         },            
  746.  
  747.         showOptions: function()
  748.         {
  749.             var windows = Components.classes["@mozilla.org/appshell/window-mediator;1"]
  750.                           .getService(Components.interfaces.nsIWindowMediator)
  751.                           .getEnumerator(null);
  752.             var windowId = "smarterwikiOptions";
  753.             while(windows.hasMoreElements())
  754.             {
  755.                 var wind = windows.getNext()
  756.                            .QueryInterface(Components.interfaces.nsIDOMWindowInternal);
  757.                 if(wind.document.documentElement.getAttribute("id") == windowId)
  758.                 {
  759.                     wind.focus();
  760.                     return wind;
  761.                 }
  762.             }
  763.  
  764.             const optionsURL = "chrome://smarterwiki/content/options.xul";
  765.             const features = "chrome, all, dialog=no, centerscreen";
  766.             return window.openDialog(optionsURL, "", features);
  767.         },
  768.  
  769.         onPopupshowing: function()
  770.         {
  771.             if(gContextMenu)
  772.             {
  773.                 if(!prefManager.getBoolPref(prefPrefix + "show_context_menu_additions"))
  774.                 {
  775.                     document.getElementById("smarterwiki-download-media").hidden = true;
  776.                     document.getElementById("smarterwiki-download-links").hidden = true;
  777.                     document.getElementById("smarterwiki-download-images").hidden = true;
  778.                     document.getElementById("smarterwiki-download-selection").hidden = true;
  779.                     document.getElementById("smarterwiki-remove-selection").hidden = true;
  780.                     //document.getElementById("smarterwiki-search-selection").hidden = true; //don't disable this one                     
  781.                 }
  782.                 else
  783.                 {
  784.                     document.getElementById("smarterwiki-download-media").hidden = false;
  785.                     document.getElementById("smarterwiki-download-links").hidden = false;
  786.                     document.getElementById("smarterwiki-download-images").hidden = false;
  787.                     document.getElementById("smarterwiki-download-selection").hidden = false;
  788.                     document.getElementById("smarterwiki-remove-selection").hidden = false;
  789.                     
  790.                     document.getElementById("smarterwiki-download-links").label = SmarterWiki.strbundle.getString("download_page_links") + " (" + 
  791.                                         SmarterWiki.getPageLinks().length + ")";
  792.                     document.getElementById("smarterwiki-download-images").label = SmarterWiki.strbundle.getString("download_page_images") + " (" + 
  793.                                         SmarterWiki.getPageImages().length + ")";
  794.  
  795.                     var remove_selection_menuitem = document.getElementById("smarterwiki-remove-selection");
  796.                     if(remove_selection_menuitem)
  797.                     {
  798.                         remove_selection_menuitem.hidden = !gContextMenu.isTextSelection();
  799.                     }
  800.  
  801.                     var download_selection_menuitem = document.getElementById("smarterwiki-download-selection");
  802.                     if(download_selection_menuitem)
  803.                     {
  804.                         download_selection_menuitem.hidden = !gContextMenu.isTextSelection();
  805.                     }
  806.  
  807.                     var download_media_menuitem = document.getElementById("smarterwiki-download-media");
  808.                     if(download_media_menuitem)
  809.                     {
  810.                         var SW_media_requests = SmarterWiki.getPageMedia();
  811.                         download_media_menuitem.hidden = SW_media_requests.length ? false : true;
  812.                         if(SW_media_requests.length)
  813.                         {
  814.                             download_media_menuitem.label = SmarterWiki.strbundle.getString("download_page_media") + " (" + 
  815.                                                                 SW_media_requests.length + ")";
  816.                         }
  817.                     }
  818.                 }
  819.                 var menuitem = document.getElementById("smarterwiki-search-selection");
  820.                 if(menuitem)
  821.                 {
  822.                     menuitem.hidden = !gContextMenu.isTextSelection();
  823.                     //var selection = window.content.getSelection();
  824.                     var focusedWindow = document.commandDispatcher.focusedWindow;
  825.                     var selection = focusedWindow.getSelection();                
  826.                     var selectionStr = selection.toString();
  827.                     var maxStrLength = 15;
  828.                     if(selectionStr.length > maxStrLength)
  829.                     {
  830.                         selectionStr = selectionStr.substring(0, maxStrLength) + "...";
  831.                     }
  832.  
  833.                     var search_wikipedia_for = SmarterWiki.strbundle.getString("search_wikipedia_for");
  834.                     menuitem.label = search_wikipedia_for.replace(/%1/g, selectionStr);
  835.                 }
  836.             }    
  837.         },
  838.         
  839.         getPageLinks: function()
  840.         {
  841.             var download_infos = [];
  842.             var added_urls = [];
  843.             var doc = document.commandDispatcher.focusedWindow.document;
  844.             var a_s = doc.getElementsByTagName("a");
  845.             for(var i = 0; i < a_s.length; i++)
  846.             {
  847.                 var url = a_s[i].toString();
  848.                 if(!(url in added_urls))
  849.                 {
  850.                     if(url.indexOf("http") == 0 || url.indexOf("ftp") == 0)
  851.                     {
  852.                         download_infos.push([ioService.newURI(url, null, null), 
  853.                             doc.documentURI ? ioService.newURI(doc.documentURI, null, null) : null,
  854.                             null, null]);
  855.                         added_urls[url] = null;
  856.                         //                        document.referrer && ioService.newURI(document.referrer, null, null) || null,
  857.                     }
  858.                 }                
  859.                 else
  860.                 {
  861.                     LOG("Duplicate url found: " + url);
  862.                 }
  863.             }
  864.             return download_infos;
  865.         },
  866.  
  867.         doDownloadPageLinks: function()
  868.         {
  869.             downloadURLs(SmarterWiki.getPageLinks());
  870.         },
  871.         
  872.         getPageImages: function()
  873.         {
  874.             var content_type_to_ext = {
  875.                 "video/x-flv": "flv", 
  876.                 "application/x-shockwave-flash": "swf",
  877.                 "image/jpeg": "jpg",
  878.                 "image/png": "png",
  879.                 "image/x-icon": "ico",
  880.                 };
  881.  
  882.             var download_infos = [];
  883.             var added_urls = [];
  884.             var doc = document.commandDispatcher.focusedWindow.document;
  885.             var img_s = doc.getElementsByTagName("img");
  886.             for(var i = 0; i < img_s.length; i++)
  887.             {
  888.                 var src = img_s[i].src;
  889.                 var uri = ioService.newURI(src, null, ioService.newURI(document.documentURI, null, null));
  890.                 var url = uri.spec;
  891.                 if(!(url in added_urls))
  892.                 {
  893.                     var file_ext = null;
  894.                     if(doc.SW_uri_content_type && uri.spec in doc.SW_uri_content_type)
  895.                     {
  896.                         file_ext = content_type_to_ext[doc.SW_uri_content_type[uri.spec]];
  897.                     }
  898.                     download_infos.push([uri, 
  899.                                 doc.documentURI ? ioService.newURI(doc.documentURI, null, null) : null,
  900.                                 file_ext, null]);
  901.                                 //document.referrer && ioService.newURI(document.referrer, null, null) || null,
  902.                     added_urls[url] = null;
  903.                 }
  904.                 else
  905.                 {
  906.                     //LOG("Duplicate url found: " + url);
  907.                 }
  908.             }
  909.             return download_infos;
  910.         },
  911.         
  912.         doDownloadPageImages: function()
  913.         {
  914.             downloadURLs(SmarterWiki.getPageImages());
  915.         },
  916.  
  917.         getPageMedia: function()
  918.         {
  919.             var download_infos = [];
  920.             var added_urls = [];
  921.             var SW_media_requests = document.commandDispatcher.focusedWindow.document.SW_media_requests;
  922.             if(!SW_media_requests)
  923.             {
  924.                 return [];
  925.             }
  926.             LOG("FOUND MEDIA_LINKS IN RESPONSE TO MENU CLICK: " + SW_media_requests);
  927.             for(var i = 0; i < SW_media_requests.length; i++)
  928.             {
  929.                 var url = SW_media_requests[i][0].spec;
  930.                 if(!(url in added_urls))
  931.                 {
  932.                     download_infos.push(SW_media_requests[i]);//[SW_media_requests[i][0], SW_media_requests[i][1]]);
  933.                     added_urls[url] = null;
  934.                 }
  935.                 else
  936.                 {
  937.                     //LOG("Duplicate url found: " + url);
  938.                 }
  939.             }
  940.             return download_infos;
  941.         },
  942.         
  943.         doDownloadPageMedia: function()
  944.         {
  945.             downloadURLs(SmarterWiki.getPageMedia());
  946.         },
  947.  
  948.         doDownloadSelection: function()
  949.         {
  950.             var focusedWindow = document.commandDispatcher.focusedWindow;
  951.             var selection = focusedWindow.getSelection();
  952.             var urls = [];
  953.             var img_s = focusedWindow.document.getElementsByTagName("img");
  954.             for(var i = 0; i < img_s.length; i++)
  955.             {
  956.                 if(selection.containsNode(img_s[i], true))
  957.                 {
  958.                     var src = img_s[i].src;
  959.                     urls.push(ioService.newURI(src, null, ioService.newURI(document.documentURI, null, null)).spec);
  960.                 }
  961.             }
  962.             var a_s = focusedWindow.document.getElementsByTagName("a");
  963.             for(var i = 0; i < a_s.length; i++)
  964.             {
  965.                 if(selection.containsNode(a_s[i], true))
  966.                 {
  967.                     var url = a_s[i].toString();
  968.                     if(url.indexOf("http") == 0 || url.indexOf("ftp") == 0)
  969.                     {
  970.                         urls.push(url);
  971.                     }
  972.                 }
  973.             }
  974.  
  975.             downloadURLs(urls, document.referrer);
  976.         },
  977.  
  978.         doSearchSelection: function()
  979.         {
  980.             var focusedWindow = document.commandDispatcher.focusedWindow;
  981.             var selection = focusedWindow.getSelection();
  982.             var selectionStr = selection.toString();
  983.  
  984.             var gBrowser = getBrowser();
  985.             gBrowser.selectedTab = gBrowser.addTab(searchWikipediaURL(selectionStr));
  986.                 //"http://smarterfox.com/wikisearch/?cx=016740879849949512001:hflecwcqo2c&cof=FORID:10&ie=UTF-8&q=" + escape(selectionStr) + "&sa=Search"
  987.                 //, "http://bitstr.org/enhancewikipedia/?");
  988.         },
  989.         
  990.         doRemoveSelection: function()
  991.         {
  992.             var selection = document.commandDispatcher.focusedWindow.getSelection();
  993.             selection.deleteFromDocument();
  994.             selection.collapseToStart();
  995.         },
  996.        
  997.         onPageLoad: function(aEvent)
  998.         {
  999.             var doc = aEvent.originalTarget; // doc is document that triggered "onload" event
  1000.             if(doc.nodeName != "#document" || !doc.location)// || doc.location.href.indexOf("chrome://") == 0
  1001.             {
  1002.                 return;
  1003.             }
  1004.             LOG("doc loaded: " + doc.location.href);
  1005.             LOG("PlacesCommandHook: " + PlacesCommandHook);
  1006.  
  1007.  
  1008.             var $ = SmarterWiki.$;
  1009.  
  1010.             var privilegeWrap = function(obj, meth)
  1011.             {
  1012.                return function() {
  1013.                    return meth.apply(obj, arguments);
  1014.                };
  1015.             };
  1016.  
  1017.             var sandbox = new Components.utils.Sandbox(doc.defaultView); //window
  1018.             sandbox.SW_$ = $;
  1019.             sandbox.SW_$getJSON = privilegeWrap($, $.getJSON);
  1020.             sandbox.SW_abortReq = function(req){ req.abort() };
  1021.             sandbox.SW_getBoolPref = privilegeWrap(prefManager, prefManager.getBoolPref);
  1022.             sandbox.SW_setBoolPref = privilegeWrap(prefManager, prefManager.setBoolPref);
  1023.             sandbox.SW_getCharPref = privilegeWrap(prefManager, prefManager.getCharPref);
  1024.             sandbox.SW_LOG = privilegeWrap(null, get_logger("smarterwiki-injected: "));
  1025.             sandbox.SW_getShortcuts = privilegeWrap(null, getShortcuts);
  1026.             sandbox.SW_hasShortcuts = privilegeWrap(null, hasShortcuts);
  1027.             sandbox.SW_addShortcut = privilegeWrap(null, addShortcut);
  1028.             sandbox.SW_getFaviconURL = privilegeWrap(null, getFaviconURL);
  1029.             sandbox.SW_openNewTab = privilegeWrap(null, openNewTab);
  1030.             sandbox.SW_removeBookmark = privilegeWrap(null, removeBookmark);
  1031.             sandbox.SW_showBookmarkCurrentPageEdit = privilegeWrap(null, showBookmarkCurrentPageEdit);
  1032.             sandbox.SW_showOptions = privilegeWrap(SmarterWiki, SmarterWiki.showOptions);
  1033.             
  1034.             
  1035.             
  1036.             
  1037.             sandbox.unsafeWindow = doc.defaultView.wrappedJSObject;
  1038.             sandbox.window = doc.defaultView;
  1039.             sandbox.document = sandbox.window.document;
  1040.             sandbox.XPathResult = Components.interfaces.nsIDOMXPathResult; // hack XPathResult
  1041.             sandbox.__proto__ = doc.defaultView;
  1042.  
  1043.             Components.utils.evalInSandbox(jquery_js, sandbox);
  1044.             async_load_popup_bubble_css();
  1045.             async_get_popup_bubble_js(function(popup_bubble_js){
  1046.                 Components.utils.evalInSandbox(popup_bubble_js, sandbox);
  1047.             });
  1048.  
  1049.             async_get_related_articles_js(function(related_articles_js){
  1050.                 Components.utils.evalInSandbox(related_articles_js, sandbox);
  1051.             });
  1052.             async_get_linkify_js(function(linkify_js){
  1053.                 Components.utils.evalInSandbox(linkify_js, sandbox);
  1054.             });
  1055.         
  1056.             
  1057.             sandbox.window.page_str = SmarterWiki.strbundle.getString("page_str");
  1058.             sandbox.window.loading_next_page_str = SmarterWiki.strbundle.getString("loading_next_page_str");
  1059.             async_load_endless_pages_css();
  1060.             async_get_endless_pages_js(function(endless_pages_js){
  1061.                 Components.utils.evalInSandbox(endless_pages_js, sandbox);
  1062.             });
  1063.  
  1064.  
  1065.             sandbox.window.add_this_shortcut = SmarterWiki.strbundle.getString("add_this_shortcut");
  1066.             sandbox.window.delete_this_shortcut = SmarterWiki.strbundle.getString("delete_this_shortcut");
  1067.             sandbox.window.press_space_to_search = SmarterWiki.strbundle.getString("press_space_to_search");
  1068.             sandbox.window.confirm_bookmark_delete = SmarterWiki.strbundle.getString("confirm_bookmark_delete");
  1069.             async_load_qlauncher_css();
  1070.             async_get_qlauncher_js(function(qlauncher_js){
  1071.                 Components.utils.evalInSandbox(qlauncher_js, sandbox);
  1072.             });
  1073.  
  1074.             
  1075.             sandbox.window.also_search_on = SmarterWiki.strbundle.getString("also_search_on");
  1076.             sandbox.window.confirm_disable = SmarterWiki.strbundle.getString("confirm_disable");
  1077.             sandbox.window.disable_label = SmarterWiki.strbundle.getString("disable_label");
  1078.             async_load_related_searches_css();
  1079.             async_get_related_searches_js(function(related_searches_js){
  1080.                 Components.utils.evalInSandbox(related_searches_js, sandbox);
  1081.             });
  1082.             
  1083.             
  1084.             sandbox.window.more_results_str = SmarterWiki.strbundle.getString("more_results");
  1085.             async_load_related_search_results_css();
  1086.             async_get_related_search_results_js(function(related_search_results_js){
  1087.                 Components.utils.evalInSandbox(related_search_results_js, sandbox);
  1088.             });
  1089.         },
  1090.     };
  1091. }();
  1092.     
  1093. window.addEventListener("load", SmarterWiki.init, false);
  1094. window.addEventListener("mouseup", SmarterWiki.onmouseup, true);
  1095. window.addEventListener("keydown", SmarterWiki.onkeydown, false);
  1096. window.addEventListener("mousedown", SmarterWiki.onmousedown, false);